# -*- coding: utf-8 -*-

import json

from apps import configs
from apps.common.base import BaseHandler, is_ruaptcha, requires_auth
from apps.plugins.email import EmailQueue
from apps.plugins.sms import send_user_verifycode_sms
from apps.utils import JsonEncoder, Utils


# 检查登录参数是否合规, 返回原因
def is_login_params(email, password):
    result = ''
    if Utils.is_null(email):
        result = '电子邮箱不能为空！'
    elif not Utils.is_email(email):
        result = '电子邮箱格式错误'
    elif Utils.is_null(password):
        result = '密码不能为空!'
    elif not Utils.is_length(6, 20, password):
        result = '密码必须是 6-20 位字符'
    return result


# 检查修改密码参数是否合规, 返回原因
def is_set_pass_params(password, newspassword):
    result = ''
    if Utils.is_null(password):
        result = '旧密码不能为空！'
    elif Utils.is_null(newspassword):
        result = '新密码不能为空！'
    elif password == newspassword:
        result = '新旧密码不可相同'
    elif not Utils.is_length(6, 20, newspassword):
        result = '新密码必须是 6-20 位字符'
    return result


# 发送验证邮件
async def send_verify_email(self, email, userid):
    code = Utils.get_token() + '_' + Utils.get_checkcode(12, False)
    if self.cache_action.verify_email().set(code, userid):
        name = '空明物联网邮箱验证'
        body = """为了保障您正常使用我们的服务，请验证您的邮箱地址， 点击<a href="{0}">立即验证邮箱</a> <br />
        如果按钮无法点击，请把下面链接<a href="{0}">{0}</a>复制到浏览器中打开""".format(
            configs.VERIFY_EMAIL_DOMAIN + '?code=' + code)
        await EmailQueue.send([email], name, body)
        return True
    else:
        return False


# 刷新用户缓存
async def flush_usercache(self, userid, token=None):
    user = await self.user_model.get_user_by_id(userid)
    del user['password']
    if token:
        user['token'] = token
    else:
        user['token'] = Utils.get_token()
    return self.cache_action.token().set(str(userid),
                                           json.dumps(user, cls=JsonEncoder))


class LoginHandler(BaseHandler):
    """
    用户登录接口  /login
    """

    @is_ruaptcha
    async def post(self, *args, **kwargs):
        email = self.get_argument('email', default='')
        password = self.get_argument('password', default='')
        error = is_login_params(email, password)
        if error:
            return self.render_json(-1, error)
        # 通过账号密码查询数据库用户信息
        user = await self.user_model.get_user_by_email_and_password(
            email, Utils.md5(Utils.aes().encrypt(password)))
        if not user:
            return self.render_json(-1, '账号或密码错误')

        if configs.OPEN_LOGIN_EMAIL and 0 != user['email_status']:
            return self.render_json(-1, '当前邮箱还没有激活，请到邮箱激活后再来')

        del user['password']
        user['token'] = Utils.get_token() + '-' + Utils.aes().encrypt(str(user['id']))

        # 将用户信息写入redis作为token缓存， 失败则返回
        token_cache = self.cache_action.token().set(
            str(user['id']), json.dumps(user, cls=JsonEncoder))
        if token_cache:
            return self.render_json(0, 'ok', {'user': user})
        else:
            return self.render_json(-1, '登录失败')


class RegisterHandler(BaseHandler):
    """
    用户注册接口 /reg
    """

    @is_ruaptcha
    async def post(self, *args, **kwargs):
        email = self.get_argument('email', default='')
        password = self.get_argument('password', default='')
        error = is_login_params(email, password)
        if error:
            return self.render_json(-1, error)
        # 邮箱被注册则返回
        if await self.user_model.get_user_by_email(email) is not None:
            return self.render_json(-1, '这个邮箱已经被注册')
        # 账号密码验证正确则写入记录
        name = 'kongming_' + Utils.get_checkcode(7, integer=False)
        if await self.user_model.add_new_user(
                name, 0, Utils.md5(Utils.aes().encrypt(password)), email):
            user = await self.user_model.get_user_by_email(email)
            # 发送激活邮箱
            if user:
                await send_verify_email(self, email, user['id'])
            return self.render_json(0, 'ok')
        else:
            return self.render_json(-1, '注册失败')


class UserInfoHandler(BaseHandler):
    """
    根据当前用户查询信息接口      /userinfo
    """

    @requires_auth
    async def get(self, cuser, *args, **kwargs):
        return self.render_json(0, 'ok', {'user': cuser})


class LoginStateHandler(BaseHandler):
    """
    检查登录状态接口  /login/state
    """

    @requires_auth
    async def get(self, *args, **kwargs):
        return self.render_json(0, 'normal')


class SetPasswordHandler(BaseHandler):
    """
    修改用户密码接口 /user/set/password
    """

    @requires_auth
    async def post(self, cuser, *args, **kwargs):
        password = self.get_argument('password', default='')
        newspassword = self.get_argument('newspassword', default='')
        # current_user = self.get_current_user()
        error = is_set_pass_params(password, newspassword)
        if error:
            return self.render_json(-1, error)
        # 通过auth查询到的用户id, 查询数据库用户信息
        userid = cuser.get('id')
        user = await self.user_model.get_user_by_id(userid)
        user_password = user['password']
        if not user:
            return self.render_json(-1, '非法访问')
        if Utils.md5(Utils.aes().encrypt(password)) == user_password:
            if await self.user_model.set_user_password(
                    userid, Utils.md5(Utils.aes().encrypt(newspassword))):
                return self.render_json(0, '密码修改成功')
            else:
                return self.render_json(-1, '密码修改失败')
        else:
            return self.render_json(-1, '旧密码验证失败')


class TestSMS(BaseHandler):
    async def get(self, *args, **kwargs):
        await send_user_verifycode_sms('17607192700', '1111')
        return self.render_json(0, 'ok')


class SendVerifyEmailHandler(BaseHandler):
    """
    发送激活邮件 /user/send_verify_email
    """



    @requires_auth
    async def post(self, cuser, *args, **kwargs):
        if cuser:
            if cuser['email_status'] == 0:
                return self.render_json(-1, '无需重复激活邮箱')
            if await send_verify_email(self, cuser['email'], cuser['id']):
                return self.render_json(0, '邮件发送成功，请查收')
            else:
                return self.render_json(-1, '邮件发送失败')


class VerifyEmailHandler(BaseHandler):
    """
    验证邮件 /user/verify_email
    """

    async def get(self, *args, **kwargs):
        code = self.get_argument('code', default='')
        if Utils.is_null(code):
            return self.render_json(-1, 'code 不能为空')
        # 通过code从缓存取到用户id
        userid = self.cache_action.verify_email().get(code)
        if not userid:
            return self.render_json(-1, 'code 效验失败')

        user = self.get_user_by_id(userid)
        if 0 == user['email_status']:
            return self.render_json(-1, '已激活邮箱，无需重复激活')

        # 修改邮箱激活状态
        if await self.user_model.set_user_email_status(userid, 0):
            await flush_usercache(self, userid)
            return self.render_json(0, 'ok')
        else:
            return self.render_json(-1, '失败')


class RetrievePasswordHandler(BaseHandler):
    """
    用户找回密码  /user/retrieve_password
    """

    @is_ruaptcha
    async def post(self):
        email = self.get_argument('email', default='')
        if Utils.is_null(email):
            return self.render_json(-1, 'email 不能为空！')
        user = await self.user_model.get_user_by_email(email)
        if not user:
            return self.render_json(-1, '用户未注册')
        code = Utils.get_token() + '_' + str(user['id']) + Utils.get_checkcode(12, False) + '_' + str(Utils.timestamp())
        if self.cache_action.reset_password().set(code, user['id']):
            name = '空明物联网重置密码'
            body = """点击<a href="{0}">立即重置密码</a> 
            <br />
            如果不是您本人操作，请忽略这封邮件。
            <br />
            如果按钮无法点击，请把下面的链接复制到浏览器中打开 <a href="{0}">{0}</a>""".format(
                configs.RESET_PASSWORD_DOMAIN + '?code=' + code)
            await EmailQueue.send([user['email']], name, body)
            return self.render_json(0, 'ok')
        else:
            return self.render_json(-1, '失败')


class ResetPasswordHandler(BaseHandler):
    """
    用户重置密码 /user/reset_password
    """

    @is_ruaptcha
    async def post(self, *args, **kwargs):
        code = self.get_argument('code', default='')
        newspassword = self.get_argument('newspassword', default='')
        if Utils.is_null(code):
            self.render_json(-1, 'code 不能为空')
        elif Utils.is_null(newspassword):
            self.render_json(-1, 'code 不能为空')
        userid = self.cache_action.reset_password().get(code)
        if not userid:
            return self.render_json(-1, '查询记录失败')
        user = await self.user_model.get_user_by_id(userid)
        if not user:
            return self.render_json(-1, '用户信息获取失败')
        else:
            if await self.user_model.set_user_password(
                    user['id'], Utils.md5(Utils.aes().encrypt(newspassword))):
                self.cache_action.reset_password().delete(code)
                return self.render_json(0, 'ok')
            else:
                return self.render_json(-1, '修改密码失败')
